import anime from 'animejs'
import { edgeConfig } from '../config/edgeConfig'
import { sizeConfig } from '../config/sizeConfig'
import { BoolType, IModuleWithState } from '../types'
import {
    $,
    createDataValue,
    getCenterPoint,
    setDomBoolVal,
    setDomDataItemVal,
    toBinaryStr,
    toInt255,
} from '../utils'
import { bus2, bus3 } from './bus'

interface IPcState {
    in_pc: BoolType
    ld_pc: BoolType
    addr: number
}

interface IPc extends IModuleWithState<IPcState> {}

/**
 * 处理编辑pc逻辑
 */
function initEditPc() {
    // 给pc的dom注册点击事件
    $('.pc .content-2')?.addEventListener('click', () => {
        // 显示模态框
        $('.pc-edit')?.classList.remove('hide')
        // 初始化模态框内的文本域的内容
        const input = $('.pc-edit input') as any
        input.value = toBinaryStr(pc.state.addr, 8, true)
    })

    // 关闭按钮
    $('.pc-edit .close')?.addEventListener('click', () => {
        $('.pc-edit')?.classList.add('hide')
        const input = $('.pc-edit input') as any
        input.value = ''
    })

    // 保存按钮
    $('.pc-edit .save')?.addEventListener('click', () => {
        const input = $('.pc-edit input') as any
        const inputVal = input.value
        pc.setState('addr', toInt255(inputVal))
        $('.pc-edit')?.classList.add('hide')
        input.value = ''
    })
}

/**
 * pc模块
 */
export const pc: IPc = {
    name: 'pc',
    state: {
        in_pc: 1,
        ld_pc: 0,
        addr: 0,
    },
    async setState(prop, value) {
        this.state[prop] = value
        if (prop === 'in_pc' || prop === 'ld_pc') {
            setDomBoolVal(prop, this.state[prop] as BoolType)
        } else if (prop === 'addr') {
            setDomDataItemVal(
                '.pc.data-item',
                'addr:' + toBinaryStr(this.state.addr)
            )
        }
        return
    },
    async neg() {
        // 在时钟下降沿触发时
        if (this.state.in_pc === 1) {
            // 若in_pc为1，则将pc中addr自增
            this.setState('addr', this.state.addr + 1)
            const pcCenter = getCenterPoint(sizeConfig.pc)
            const pcTopCenter = getCenterPoint(sizeConfig.pc, 'top')
            const data = createDataValue(
                this.state.addr,
                toBinaryStr(this.state.addr),
                pcCenter
            )
            const timeline = anime.timeline({
                targets: data.dom,
                duration: (edgeConfig.time.neg + edgeConfig.time.low) * 0.05,
                easing: 'linear',
            })
            return timeline.add({
                x: pcTopCenter.x,
                y: pcTopCenter.y - 10,
                complete: () => {
                    bus2.setData(this.state.addr)
                    data.dom.remove()
                },
            }).finished
        } else if (this.state.ld_pc === 1) {
            const pcCenter = getCenterPoint(sizeConfig.pc)
            const pcBottomCenter = getCenterPoint(sizeConfig.pc, 'bottom')
            const pcTopCenter = getCenterPoint(sizeConfig.pc, 'top')
            const value = bus3.getData()
            const data = createDataValue(
                value,
                toBinaryStr(value),
                pcBottomCenter
            )
            // inputs的第一项的值移动到pc中心
            const timeline = anime.timeline({
                targets: data.dom,
                duration: (edgeConfig.time.neg + edgeConfig.time.low) * 0.05,
                easing: 'linear',
            })
            return timeline
                .add({
                    x: pcCenter.x,
                    y: pcCenter.y,
                    complete: () => {
                        // 把值赋值给pc.addr
                        this.setState('addr', value)
                    },
                })
                .add({
                    x: pcTopCenter.x,
                    y: pcTopCenter.y - 10,
                    delay: 100,
                    complete: () => {
                        bus2.setData(value)
                        data.dom.remove()
                    },
                }).finished
        }
    },
    init() {
        // 设置in_pc的初始值
        setDomBoolVal('in_pc', this.state.in_pc)
        // 设置ld_pc的初始值
        setDomBoolVal('ld_pc', this.state.ld_pc)
        // 设置addr的初始值
        setDomDataItemVal(
            '.pc.data-item',
            'addr:' + toBinaryStr(this.state.addr)
        )
        // 编辑pc
        initEditPc()
    },
}
